﻿using Newtonsoft.Json;
using StockMarketTool.Helper;
using StockMarketTool.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace StockMarketTool.ViewModel
{
    public class MainViewModel : NotifyBase
    {
        #region 字段
        private Thread updateThread;
        private int updateInterval = 1000;
        private bool _updateing = false;

        private int shCount = 0;
        private int szCount = 0;
        private List<StockModel> shlist;
        private List<StockModel> szlist;
        #endregion

        #region 属性
        //private bool _needUpdate;
        ///// <summary>
        ///// 是否刷新，控制线程
        ///// </summary>
        //public bool NeedUpdate
        //{
        //    get { return _needUpdate; }
        //    set
        //    {
        //        _needUpdate = value;
        //        RaisePropertyChanged("NeedUpdate");
        //    }
        //}
        private string _inputCode;
        /// <summary>
        /// 输入的代码
        /// </summary>
        public string InputCode
        {
            get { return _inputCode; }
            set
            {
                _inputCode = value;
                RaisePropertyChanged("InputCode");
            }
        }

        private CodeValueModel _showValue;
        /// <summary>
        /// 显示值
        /// </summary>
        public CodeValueModel ShowValue
        {
            get { return _showValue; }
            set
            {
                _showValue = value;
                RaisePropertyChanged("ShowValue");
            }
        }
        private ObservableCollection<CodeValueModel> _valueList;
        /// <summary>
        /// 值列表
        /// </summary>
        public ObservableCollection<CodeValueModel> ValueList
        {
            get { return _valueList; }
            set
            {
                _valueList = value;
                RaisePropertyChanged("ValueList");
            }
        }
        private CodeValueModel _selectedValue;
        /// <summary>
        /// 已选择的项（设置界面用到）
        /// </summary>
        public CodeValueModel SelectedValue
        {
            get { return _selectedValue; }
            set
            {
                _selectedValue = value;
                RaisePropertyChanged("SelectedValue");
            }
        }
        private List<StockModel> _stockList;
        /// <summary>
        /// 股票列表（沪深）
        /// </summary>
        public List<StockModel> StockList
        {
            get { return _stockList; }
            set
            {
                _stockList = value;
                RaisePropertyChanged("StockList");
            }
        }
        private bool _autoRun;
        /// <summary>
        /// 是否自启动
        /// </summary>
        public bool AutoRun
        {
            get { return _autoRun; }
            set
            {
                _autoRun = value;
                RaisePropertyChanged("AutoRun");
            }
        }
        #endregion

        #region 命令、事件
        /// <summary>
        /// 添加
        /// </summary>
        public RelayCommand AddCommand { get; set; }
        /// <summary>
        /// 删除
        /// </summary>
        public RelayCommand DeleteCommand { get; set; }
        /// <summary>
        /// 设置自启动
        /// </summary>
        public RelayCommand SetAutoRunCommand { get; set; }
        /// <summary>
        /// 创建桌面快捷方式
        /// </summary>
        public RelayCommand CreateShortCutCommand { get; set; }

        /// <summary>
        /// 创建桌面快捷方式
        /// </summary>
        private void CreateShortCut()
        {
            AutoRunHelper.CreateDesktopQuick(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
                CacheInfo.QuickName, System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
        }
        /// <summary>
        /// 设置自启动
        /// </summary>
        private void SetAutoRun()
        {
            AutoRunHelper.SetAutoStart(AutoRun);
        }
        /// <summary>
        /// 删除
        /// </summary>
        private void Delete()
        {
            if (this.SelectedValue == null)
            {
                MessageBox.Show("选择删除项");
                return;
            }
            bool needresetSelected = this.SelectedValue.IsShow;

            this.ValueList.Remove(this.SelectedValue);

            if (needresetSelected)
            {
                if (this.ValueList.Count > 0)
                {
                    this.SelectedValue = ValueList[0];
                    this.SelectedValue.IsShow = true;
                }
            }
        }
        /// <summary>
        /// 添加
        /// </summary>
        private void Add()
        {
            if (!String.IsNullOrWhiteSpace(this.InputCode))
            {
                foreach (CodeValueModel c in this.ValueList)
                    c.Status = ItemStatus.None;
                var cvms = this.ValueList.Where(p => p.Code == this.InputCode);
                if (cvms != null && cvms.Count() > 0)
                {
                    MessageBox.Show("已在当前列表");
                    this.InputCode = "";
                    return;
                }
                CodeValueModel newitem = new CodeValueModel()
                {
                    Code = this.InputCode,
                    Name = this.StockList.SingleOrDefault(p => p.symbol == this.InputCode)?.name,
                    Status = ItemStatus.Add
                };
                this.ValueList.Insert(0, newitem);
                if (this.ValueList.Count == 1)
                    SetShowValue(ValueList[0].Code);

                this.InputCode = "";
                //立刻更新
                ProcUpdate();
            }
        }
        #endregion

        #region 公共方法
        public MainViewModel()
        {
            this.ValueList = new ObservableCollection<CodeValueModel>();
            this.StockList = new List<StockModel>();
            InitConfig();

            AddCommand = new RelayCommand(Add);
            DeleteCommand = new RelayCommand(Delete);
            SetAutoRunCommand = new RelayCommand(SetAutoRun);
            CreateShortCutCommand = new RelayCommand(CreateShortCut);

            updateThread = new Thread(Update);
            updateThread.IsBackground = true;
            updateThread.Start();

            CheckTimeHelper.CheckTime();
        }

        public void SetNotifyItem(CodeValueModel item)
        {
            CodeValueModel cvm = this.ValueList.SingleOrDefault(c => c.Code == item.Code);
            if (cvm != null)
            {
                cvm.NotifyType = item.NotifyType;
                cvm.NotifyValue = item.NotifyValue;
            }
        }
        public void SetShowValue(string code)
        {
            if (this.ShowValue?.Code == code)
                return;

            CodeValueModel cvm = this.ValueList.SingleOrDefault(p => p.Code == code);
            if (cvm != null)
            {
                foreach (CodeValueModel item in this.ValueList)
                {
                    item.IsShow = false;
                    item.Status = ItemStatus.None;
                }
                this.ValueList.Remove(cvm);
                cvm.Status = ItemStatus.Focus;
                if (this.ValueList.Count > 0)
                    this.ValueList.Insert(0, cvm);
                else
                    this.ValueList.Add(cvm);
                cvm.IsShow = true;
                this.ShowValue = cvm;
            }
        }
        public void SaveConfig()
        {
            try
            {
                Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                StringBuilder sbconfig = new StringBuilder();
                foreach (CodeValueModel item in this.ValueList)
                {
                    sbconfig.Append(item.Code + ",");
                    if (!String.IsNullOrWhiteSpace(item.Name))//名称不为空，说明股票存在
                    {
                        //股票列表不存在，说明是新股票，保存
                        if (!StockList.Exists(p => p.symbol == item.Code))
                        {
                            if (item.Code.Contains("sh"))
                            {
                                this.shlist.Add(new StockModel()
                                {
                                    code = item.Code.Replace("sh", ""),
                                    name = item.Name,
                                    symbol = item.Code
                                });
                            }
                            else if (item.Code.Contains("sz"))
                            {
                                this.szlist.Add(new StockModel()
                                {
                                    code = item.Code.Replace("sz", ""),
                                    name = item.Name,
                                    symbol = item.Code
                                });
                            }
                        }
                    }
                }
                if (sbconfig.Length > 0)
                    sbconfig.Remove(sbconfig.Length - 1, 1);
                config.AppSettings.Settings["Codes"].Value = sbconfig.ToString();
                config.AppSettings.Settings["ShowCode"].Value = this.ShowValue.Code;
                config.Save();

                //现有的列表比原有大，说明有新增的，保存到本地列表
                if (this.shlist.Count > shCount)
                    File.WriteAllText("Data/StockListsh.json", JsonConvert.SerializeObject(shlist));
                if (this.szlist.Count > szCount)
                    File.WriteAllText("Data/StockListsz.json", JsonConvert.SerializeObject(szlist));
            }
            catch (Exception ex)
            {
                LogHelper.LogError(ex, "保存配置出错：");
            }
        }
        #endregion

        #region 私有方法
        private void InitConfig()
        {
            try
            {
                string stocklistjson = File.ReadAllText("Data/StockListsh.json");
                shlist = JsonConvert.DeserializeObject<List<StockModel>>(stocklistjson);
                stocklistjson = File.ReadAllText("Data/StockListsz.json");
                szlist = JsonConvert.DeserializeObject<List<StockModel>>(stocklistjson);
                this.StockList.AddRange(shlist);
                this.StockList.AddRange(szlist);
                this.shCount = shlist.Count;
                this.szCount = szlist.Count;


                string codes = AppSettingHelper.GetValue<string>("Codes");
                string showcode = AppSettingHelper.GetValue<string>("ShowCode");
                CacheInfo.UpdateWhenMarketClosed = AppSettingHelper.GetValue<bool>("UpdateWhenMarketClosed", false);
                if (!String.IsNullOrWhiteSpace(codes))
                {
                    List<string> codelist = codes.Split(',').ToList();
                    if (codelist.Count > 0)
                    {
                        ValueList = new ObservableCollection<CodeValueModel>();
                        int sort = 1;
                        codelist.ForEach(p =>
                        {
                            StockModel stm = this.StockList.SingleOrDefault(s => s.symbol == p);
                            ValueList.Add(new CodeValueModel()
                            {
                                Code = p,
                                Name = stm?.name,
                                Sort = sort++
                            });
                        });
                        this.ShowValue = ValueList.SingleOrDefault(p => p.Code == showcode);
                        if (this.ShowValue == null)
                        {
                            SetShowValue(ValueList[0].Code);
                        }
                        this.ShowValue.IsShow = true;
                    }
                }
                else
                {
                    this.ShowValue = new CodeValueModel() { Code = "" };
                }
            }
            catch (Exception ex)
            {
                LogHelper.Log("加载配置文件出错：" + ex.Message);
            }
        }
        private void Update()
        {
            while (true)
            {
                ProcUpdate();
                Thread.Sleep(updateInterval);
            }
        }
        private void ProcUpdate()
        {
            if (_updateing)
                return;
            _updateing = true;
            try
            {
                if (CheckTimeHelper.NeedRefresh)
                {
                    if (this.ValueList.Count == 0)
                    {
                        _updateing = false;
                        return;
                    }
                    /*
                     * var hq_str_s_sz000729="燕京啤酒,7.45,0.17,2.34,392908,29298";
                     * var hq_str_s_sh601168 = "西部矿业,15.740,0.580,3.83,1118039,176687";
                    */
                    //只关心当前价格、涨跌幅度
                    List<string> codelist = new List<string>();
                    foreach (CodeValueModel item in this.ValueList)
                        codelist.Add(item.Code);
                    string rs = StockQueryHelper.GetDataByCode(codelist, StockDataRequestEnum.Index);
                    if (String.IsNullOrWhiteSpace(rs))
                    {
                        _updateing = false;
                        LogHelper.Log("网络有问题，先睡个两秒再查。");
                        Thread.Sleep(2000);
                        return;
                    }
                    Regex reg = new Regex("hq_str_s_(?<code>.*?)=\"(?<value>.*?)\";", RegexOptions.None);
                    MatchCollection matchs = reg.Matches(rs);
                    if (matchs.Count > 0)
                    {
                        foreach (Match match in matchs)
                        {
                            string code = match.Groups["code"].Value;
                            string value = match.Groups["value"].Value;
                            if (!String.IsNullOrWhiteSpace(code) && !String.IsNullOrWhiteSpace(value))
                            {
                                string[] vs = value.Split(',');
                                CodeValueModel cvm = this.ValueList.SingleOrDefault(c => c.Code == code);
                                if (cvm != null)
                                {
                                    cvm.CurValue = double.Parse(vs[1]);
                                    cvm.PrinceChange = double.Parse(vs[2]);
                                    cvm.PrinceChangePercent = double.Parse(vs[3]);
                                    bool arriveNotify = false;
                                    switch (cvm.NotifyType)
                                    {
                                        case NotifyTypeEnums.价格:
                                            arriveNotify = ArriveNotifyValue(cvm.CurValue, cvm.NotifyValue, cvm.IsLestThen);
                                            break;
                                        case NotifyTypeEnums.价格变动:
                                            arriveNotify = ArriveNotifyValue(cvm.PrinceChange, cvm.NotifyValue);
                                            break;
                                        case NotifyTypeEnums.价格变动百分比:
                                            arriveNotify = ArriveNotifyValue(cvm.PrinceChangePercent, cvm.NotifyValue);
                                            break;
                                        case NotifyTypeEnums.不提醒:
                                        default:
                                            break;
                                    }
                                    if (arriveNotify)
                                    {
                                        AlertMsgWin.GetInstance().Show(cvm.Name + ":" + cvm.NotifyType + "已到达设定值", cvm.PlayNotifyMusic);
                                        cvm.NotifyType = NotifyTypeEnums.不提醒;
                                        cvm.NotifyValue = null;
                                    }
                                    cvm.Name = vs[0];
                                    if (cvm.Code == this.ShowValue.Code)
                                    {
                                        this.ShowValue = cvm;
                                    }
                                }
                                else
                                    this.ValueList.Add(cvm);
                            }
                        }
                        if (this.ShowValue == null)
                        {
                            this.ShowValue = ValueList[0];
                            this.ShowValue.IsShow = true;
                        }
                        else if (string.IsNullOrWhiteSpace(this.ShowValue.Code))
                        {
                            this.ShowValue = ValueList[0];
                            this.ShowValue.IsShow = true;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.LogError(ex, "刷新数据出错：");
            }
            finally
            {
                _updateing = false;
            }

        }
        private bool ArriveNotifyValue(double v1, double? v2, bool? islestthen = null)
        {
            if (v2 == null)
                return false;
            if (islestthen != null)
            {
                if ((bool)islestthen)
                {
                    return v1 <= v2;
                }
                else
                {
                    return v1 >= v2;
                }
            }
            else
            {
                return v1 >= v2;
            }
            //if (v2 < 0)
            //{
            //    return v1 <= v2;
            //}
            //else
            //{
            //    return v1 >= v2;
            //}
        }
        #endregion
    }
}
